﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Common
{
    /// <summary>
    /// Tcp服务端
    /// </summary>
    public class TcpServerWorker : BackgroundService
    {
        private readonly Logger _logger;
        private readonly IServiceProvider _serviceProvider;
        private readonly List<TcpHostWorker> _workers = new List<TcpHostWorker>();

        private TcpListener tcpListener;

        public IPAddress IPAddress { get; set; } = IPAddress.Any;

        public Int32 Port { get; set; }

        /// <summary>
        /// 结束标记
        /// </summary>
        public Int32 LineOff { get; set; } = (int)'\n';

        /// <summary>
        /// 接收到消息
        /// </summary>
        public event Action<Message, CancellationToken> ReceiveMessage;

        /// <summary>
        /// 断开连接
        /// </summary>
        public event Action<TcpHostWorker, CancellationToken> UnConnected;

        /// <summary>
        /// 已经连接
        /// </summary>
        public event Action<TcpHostWorker, CancellationToken> Connectionned;

        /// <summary>
        /// 检查结束符位置
        /// </summary>
        public event Func<byte[], int> LineOffCheck;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="serviceProvider"></param>
        public TcpServerWorker(Logger logger, IServiceProvider serviceProvider)
        {
            _logger = logger;
            _serviceProvider = serviceProvider;
        }

        public override Task StartAsync(CancellationToken cancellationToken)
        {
            tcpListener = new TcpListener(IPAddress, Port);
            tcpListener.Start();
            return base.StartAsync(cancellationToken);
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                var tcpHostWork = _serviceProvider.GetService<TcpHostWorker>();
                tcpHostWork.TcpHost = await tcpListener.AcceptTcpClientAsync(stoppingToken);
                tcpHostWork.ReceiveMessage += ReceiveMessage; ;//接收到消息事件注册
                tcpHostWork.Connectionned += Connectionned; ;//注册已连接事件
                tcpHostWork.LineOffCheck += LineOffCheck;//注册结束符检查事件
                tcpHostWork.UnConnected += TcpHostWork_UnConnected;//客户端断开连接
                _workers.Add(tcpHostWork);
                await tcpHostWork.StartAsync(stoppingToken);
            }
        }

        /// <summary>
        /// 客户端断开连接
        /// </summary>
        /// <param name="hostWorker"></param>
        /// <param name="cancellationToken"></param>
        private void TcpHostWork_UnConnected(TcpHostWorker hostWorker, CancellationToken cancellationToken)
        {
            UnConnected?.Invoke(hostWorker, cancellationToken);
            hostWorker.ReceiveMessage -= ReceiveMessage;
            hostWorker.UnConnected -= TcpHostWork_UnConnected;
            _workers.Remove(hostWorker);
        }

        /// <summary>
        /// 停止服务
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override Task StopAsync(CancellationToken cancellationToken)
        {
            tcpListener.Stop();
            if (_workers.Count > 0)
            {
                foreach (var item in _workers)
                {
                    item.StopAsync(cancellationToken);
                }
                _workers.Clear();
            }
            return base.StopAsync(cancellationToken);
        }


    }
}
